package com.wkbb.sports.utils;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.wkbb.sports.model.HlifeWorkStudent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author lbh
 * @date 2021年04月17日 20:55:27
 * @description: Redis实现排行榜功能 优化mysql查询的方式
 * 既能够去重又能够保持有序
 * workId为作业id
 * id为hlife_work_student表的主键id
 */
@Component
@Slf4j
public class RedisOfRank {

        @Autowired
        private RedisTemplate redisTemplate;

        /**
         * 1、批量新增
         */
        public  void batchAdd(Integer workId,List<Map<String,Object>> mapList) {
//            Set<ZSetOperations.TypedTuple<Integer>> tuples = new HashSet<>();
            Set<ZSetOperations.TypedTuple<Map<String,Object>>> tuples = new HashSet<>();
            mapList.forEach(map->{
//                DefaultTypedTuple<Integer> tuple = new DefaultTypedTuple<>(Integer.parseInt(String.valueOf(map.get("id"))), Double.valueOf(String.valueOf(map.get("score"))));
                DefaultTypedTuple<Map<String,Object>> tuple = new DefaultTypedTuple<>((Map<String,Object>)map.get("perInfo"), Double.valueOf(String.valueOf(map.get("score"))));
                tuples.add(tuple);
            });

            Long num = redisTemplate.opsForZSet().add(workId, tuples);
            log.info("========受影响行数：" + num);
        }

        /**
         *2、获取某个作业的全部学生信息排行列表
         * 获取前1000名(根据分数倒序)
         * 假设一个班级的学生有1000人，就是查询该作业所有参与学生的排名
         */
        public  Set list(Integer workId) {
            Set<ZSetOperations.TypedTuple<Map<String,Object>>> rangeWithScores = redisTemplate.opsForZSet().reverseRangeWithScores(workId, 0, 1000);
             log.info("========获取到的排行和分数列表:" + JSON.toJSONString(rangeWithScores));
             return rangeWithScores;
        }

        /**
         *3、获取某个作业的全部学生分数排行列表
         * 获取前1000名(根据分数倒序)
         * 假设一个班级的学生有1000人，就是查询该作业所有参与学生的排名
         */
        public  Set listScore(Integer workId) {
            Set<String> range = redisTemplate.opsForZSet().reverseRange(workId, 0, 1000);
            log.info("========获取到的排行列表:" + JSON.toJSONString(range));
            return range;
        }

        /**
         * 4、单个新增，同时返回自己的排名
         */
        /*public  Long add(Integer workId,Integer id,double score) {
            redisTemplate.opsForZSet().add(workId, id, score);
            return findRankNum(workId,id);
        }*/
//        public  Long add(HlifeWorkStudent hlifeWorkStudent) {
//            //====================================================
//            Integer id=hlifeWorkStudent.getId();
//            Integer studentId=hlifeWorkStudent.getStudentId();
//            String studentName=hlifeWorkStudent.getStudentName();
//            String headImgUrl=hlifeWorkStudent.getHeadImgUrl();
//            Double score=hlifeWorkStudent.getScore();
//            Integer workId=hlifeWorkStudent.getWorkId();
//
//            Map<String,Object> map= Maps.newHashMap();
//            map.put("id",id);
//            map.put("studentId",studentId);
//            map.put("studentName",studentName);
//            map.put("headImgUrl",headImgUrl);
////            map.put("score",score);
//            map.put("workId",workId);
//            //====================================================
//
//            redisTemplate.opsForZSet().add(workId, map, score);
//            return findRankNum(workId,map);
//        }

        /**
         *5、获取某个作业某个人的排行
         * 获取李四单人的排行
         */
        /*public  Long findRankNum(Integer workId,Integer id){
            Long rankNum = redisTemplate.opsForZSet().reverseRank(workId, id);
             log.info("======workId为"+workId+"==id为"+id+"的个人排名：" + rankNum);
             return rankNum;
        }*/
        public  Long findRankNum(Integer workId,Map<String,Object> map){
            Long rankNum = redisTemplate.opsForZSet().reverseRank(workId, map);
            log.info("======workId为"+workId+"==map为："+JSON.toJSONString(map)+"的个人排名：" + rankNum);
            return rankNum;
        }

        /**
         *6、获取某个作业某个人的分数
         * 获取李四单人的分数
         */
        /*public  Double findScore(Integer workId,Integer id){
            Double score = redisTemplate.opsForZSet().score(workId, id);
            log.info("========id为"+id+"的分数:" + score);
            return score;
        }*/
        public  Double findScore(Integer workId,Map<String,Object> map){
            Double score = redisTemplate.opsForZSet().score(workId, map);
            log.info("======workId为"+workId+"==map为"+JSON.toJSONString(map)+"的分数：" + score);
            return score;
        }

        /**
         * 7、统计某个作业两个分数之间的人数
         */
        public  Long count(Integer workId,double min,double max){
            Long count = redisTemplate.opsForZSet().count(workId, min, max);
             log.info("========统计"+min+"-"+max+"之间的人数:" + count);
             return count;
        }

        /**
         *8、获取整个集合的基数(数量大小)，某个作业已做的学生人数
         */
        public  Long zCard(Integer workId){
            Long aLong = redisTemplate.opsForZSet().zCard(workId);
             log.info("=====workId为："+workId+"===的作业已做的学生人数：" + aLong);
             return aLong;
        }


        /**
         * 9、使用加法操作分数
         */
        public  Double incrementScore(Integer workId,Integer id,double score){
            Double score1 = redisTemplate.opsForZSet().incrementScore(workId, id, score);
             log.info("========李四分数+1000后：" + score1);
             return score1;
        }

        /**
         * 10、清空某一个作业的排行榜记录
         */
        public  void removeAllByWorkId(Integer workId){
            long num=redisTemplate.opsForZSet().remove(workId);
             log.info("========清空作业id为："+workId+"的"+num+"条排行榜记录========" );
        }

}
